package main

import (
	"context"
	blobpb "coolcar/v1/blob/api/gen/v1"
	carpb "coolcar/v1/car/api/gen/v1"
	rentalpb "coolcar/v1/rental/api/gen/v1"
	"coolcar/v1/rental/profile"
	profileDao "coolcar/v1/rental/profile/dao"
	"coolcar/v1/rental/trip"
	"coolcar/v1/rental/trip/client/car"
	"coolcar/v1/rental/trip/client/poi"
	profileClient "coolcar/v1/rental/trip/client/profile"
	tripDao "coolcar/v1/rental/trip/dao"
	"coolcar/v1/shared/server"
	"coolcar/v1/shared/zaplog"
	"github.com/namsral/flag"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"google.golang.org/grpc"
	"log"
	"time"
)

var (
	mongodbName = "coolcar"
)

var addr = flag.String("addr", ":8082", "address to listen")
var mongoURI = flag.String("mongo_uri", "mongodb://localhost:27017/?readPreference=primary&ssl=false", "mongo uri")
var blobAddr = flag.String("blob_addr", ":8083", "blob addr")
var carAddr = flag.String("car_addr", ":8084", "car addr")
var authPublicKeyFile = flag.String("auth_public_key_file", "<PUBLICKEY>", "auth public key file")

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	sugar, err := zaplog.NewZapLogger()
	if err != nil {
		log.Fatalf("failed to create logger: %v", err)
	}
	defer sugar.Sync()

	mc, err := mongo.Connect(ctx, options.Client().ApplyURI(*mongoURI))
	if err != nil {
		sugar.Fatalf("failed to connect mongodb: %v", err)
	}
	db := mc.Database(mongodbName)

	conn, err := grpc.Dial(*blobAddr, grpc.WithInsecure())
	if err != nil {
		sugar.Fatalf("failed to dial profileServiceClient: %v", err)
	}

	profService := &profile.Service{
		BlobClient:         blobpb.NewBlobServiceClient(conn),
		Sugar:              sugar,
		Mongo:              profileDao.NewMongo(db),
		PhotoGetExpired:    5 * time.Second,
		PhotoUploadExpired: 10 * time.Second,
	}

	carConn, err := grpc.Dial(*carAddr, grpc.WithInsecure())
	if err != nil {
		sugar.Fatalf("failed to dial CarManager: %v", err)
	}

	sugar.Fatal(server.RunGRPCServer(&server.Config{
		Name:              "rental",
		Addr:              *addr,
		AuthPublicKeyFile: *authPublicKeyFile,
		RegisterFunc: func(g *grpc.Server) {
			rentalpb.RegisterTripServiceServer(g, &trip.Service{
				Sugar: sugar,
				Mongo: tripDao.NewMongo(db),
				ProfileManager: &profileClient.Manager{
					Fetcher: &profile.Service{
						Sugar: sugar,
						Mongo: profileDao.NewMongo(db),
					},
				},
				CarManager: &car.Manager{
					CarService: carpb.NewCarServiceClient(carConn),
				},
				POIManager: &poi.Manager{},
			})
			rentalpb.RegisterProfileServiceServer(g, profService)
		},
		Suger: sugar,
	}))
}
